package net.maku.framework.common.utils;

import com.alibaba.fastjson.JSON;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 网络工具类，参考：
 * http://www.cnblogs.com/nihaorz/p/5334208.html
 * http://www.jianshu.com/p/ca8a982a116b
 * http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html（推荐）
 *
 * @author jolley
 */
public class NetworkUtils {

    private static Logger log = LoggerFactory.getLogger(NetworkUtils.class);

    public static String doGet(String url) {
        return doGet(url, 0,null);
    }

    /**
     * GET请求数据
     *
     * @param url
     * @return
     */
    public static String doGet(String url, int socketTimeout,Headers headers) {
        String respData = null;
        long sn = System.currentTimeMillis();

        try {
            if (!url.startsWith("http://") && !url.startsWith("https://")) {
                url = "http://" + url;
            }

            log.info("jolley>> sn: {}, doGet url: {}", sn, url);
            OkHttpClient client = new OkHttpClient();
            if (socketTimeout > 0) {
                OkHttpClient.Builder builder = client.newBuilder();
                builder.connectTimeout(socketTimeout, TimeUnit.SECONDS);
                client = builder.build();
            }

            Request request = null;
            if(headers==null){
                request = new Request.Builder()
                        .url(url)
                        .build();
            }else{
                request=new Request.Builder()
                        .url(url)
                        .headers(headers)
                        .build();
            }

            OkHttpClient client1 = new OkHttpClient().newBuilder()
                    .build();
            Request request1 = new Request.Builder()
                    .url("http://47.104.195.12:60005/gd/device/deviceInfo?deviceNum=GDZS23092183")
                    .addHeader("Authorization", "interface_121_d70e35eb825a48c8bd0c3c040d851e9e20231218002146")
//                    .addHeader("User-Agent", "apifox/1.0.0 (https://www.apifox.cn)")
                    .build();
            try {
                Response response = client1.newCall(request1).execute();
                log.info("response");
            } catch (IOException e) {
                e.printStackTrace();
            }

            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) {
                throw new IOException("服务器端错误: " + response);
            }

            respData = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (respData != null && respData.length() > 400) {
            log.info("jolley>> sn: {}, doGet url: {}, response: {} ...", sn, url, respData.substring(0, 400));
        } else {
            log.info("jolley>> sn: {}, doGet url: {}, response: {}", sn, url, respData);
        }
        return respData;
    }

    public static String doPost(String url, String body) {
        return doPost(url, body, null, 0, null);
    }

    /**
     * POST提交数据
     *
     * @param url
     * @param body
     * @param meiatype
     * @param socketTimeout
     * @return
     */
    public static String doPost(String url, String body, String meiatype, int socketTimeout, Headers headers) {
        String respData = null;

        long sn = System.currentTimeMillis();
        try {
            if (!url.startsWith("http://") && !url.startsWith("https://")) {
                url = "http://" + url;
            }

            log.info("jolley>> sn: {}, doPost url: {}, body: {}", sn, url, body);
            OkHttpClient client = new OkHttpClient();
            if (socketTimeout > 0) {
                OkHttpClient.Builder builder = client.newBuilder();
                builder.connectTimeout(socketTimeout, TimeUnit.SECONDS);
                client = builder.build();
            }

            if (StringUtils.isEmpty(meiatype)) {
                meiatype = "text/plain; charset=utf-8";
            }
            MediaType MEDIA_TYPE = MediaType.parse(meiatype);
            RequestBody stringBody = RequestBody.create(MEDIA_TYPE, body == null ? "" : body);


            Request request = null;
            if (headers == null) {
                request = new Request.Builder()
                        .url(url)
                        .post(stringBody)
                        .build();
            } else {
                request = new Request.Builder()
                        .url(url)
                        .headers(headers)
                        .post(stringBody)
                        .build();
            }

            Response response = client.newCall(request).execute();

            if (!response.isSuccessful()) {
                throw new IOException("服务器端错误: " + response);
            }
            respData = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (respData != null && respData.length() > 400) {
            log.info("jolley>> sn: {}, doPost url: {}, response: {} ...", sn, url, respData.substring(0, 400));
        } else {
            log.info("jolley>> sn: {}, doPost url: {}, response: {}", sn, url, respData);
        }
        return respData;
    }

    public static String doPostForm(String url, Map<String, String> map) {
        return doPostForm(url, map, 0, null);
    }

    /**
     * POST表单提交数据
     *
     * @param url
     * @param map
     * @param socketTimeout 请求超时时间，单位秒
     * @return
     */
    public static String doPostForm(String url, Map<String, String> map, int socketTimeout, Headers headers) {
        String respData = null;

        long sn = System.currentTimeMillis();
        try {
            if (!url.startsWith("http://") && !url.startsWith("https://")) {
                url = "http://" + url;
            }

            String body = "";
            if (map != null) {
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    body += entry.getKey() + " => " + entry.getValue() + "    ";
                }
            }
            log.info("jolley>> sn: {}, doPost url: {}, body: {}", sn, url, body);
            OkHttpClient client = new OkHttpClient();
            if (socketTimeout > 0) {
                OkHttpClient.Builder builder = client.newBuilder();
                builder.connectTimeout(socketTimeout, TimeUnit.SECONDS);
                client = builder.build();
            }

            FormBody.Builder builder = new FormBody.Builder();
            if (map != null) {
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    builder.add(entry.getKey(), entry.getValue());
                }
            }
            RequestBody formBody = builder.build();
            Request request = null;
            if (headers == null) {
                request = new Request.Builder()
                        .url(url)
                        .post(formBody)
                        .build();
            } else {
                request = new Request.Builder()
                        .url(url)
                        .headers(headers)
                        .post(formBody)
                        .build();
            }

            Response response = client.newCall(request).execute();

            if (!response.isSuccessful()) {
                throw new IOException("服务器端错误: " + response);
            }

            respData = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (respData != null && respData.length() > 400) {
            log.info("jolley>> sn: {}, doPost url: {}, response: {} ...", sn, url, respData.substring(0, 400));
        } else {
            log.info("jolley>> sn: {}, doPost url: {}, response: {}", sn, url, respData);
        }
        return respData;
    }


    /**
     * 上传文件
     *
     * @param url
     * @param filePath
     * @param meiatype text/x-markdown; charset=utf-8
     *                 application/json; charset=utf-8
     *                 image/png
     * @return
     */
    public static String upload(String url, String filePath, String meiatype) {
        return upload(url, null, filePath, meiatype);
    }

    /**
     * 提交分块请求
     *
     * @param url
     * @param mapHeads
     * @param filePath
     * @param meiatype text/x-markdown; charset=utf-8
     *                 application/json; charset=utf-8
     *                 image/png
     * @return
     */
    public static String upload(String url, Map<String, String> mapHeads, String filePath, String meiatype) {
        String respData = null;

        long sn = System.currentTimeMillis();
        try {
            log.info("jolley>> sn: {}, upload url: {}, filePath: {}", sn, url, filePath);
            File file = new File(filePath);
            if (!file.exists() || !file.isFile()) {
                throw new IOException("文件不存在");
            }

            OkHttpClient client = new OkHttpClient();

            if (StringUtils.isEmpty(meiatype)) {
                meiatype = "text/x-markdown; charset=utf-8";
            }
            MediaType MEDIA_TYPE = MediaType.parse(meiatype);
            RequestBody fileBody = RequestBody.create(MEDIA_TYPE, file);

            MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
            if (mapHeads != null) {
                for (String key : mapHeads.keySet()) {
                    builder.addFormDataPart(key, mapHeads.get(key));
                }
            }
            String filename = filePath.split("/")[filePath.split("/").length - 1];
            builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"file\";filename=\"" + filename + "\""), fileBody);
            RequestBody requestBody = builder.build();

            Request request = new Request.Builder()
                    .header("Authorization", "Client-ID " + "---.123.---")
                    .url(url)
                    .post(requestBody)
                    .build();

            Response response = client.newCall(request).execute();

            if (!response.isSuccessful()) {
                throw new IOException("服务器端错误: " + response);
            }
//			Headers responseHeaders = response.headers();
//			for(int i = 0; i < responseHeaders.size(); i++) {
//				System.out.println("jolley>> " + responseHeaders.name(i) + ": " + responseHeaders.value(i));
//			}

            respData = response.body().string();
        } catch (Exception e) {
            e.printStackTrace();
        }

        log.info("jolley>> sn: {}, doPost response: {}", sn, respData);
        return respData;
    }

    /**
     * 下载文件
     *
     * @param url
     * @param path 以/结尾表示目录，否则表示文件
     * @return 成功返回下载路径，失败null
     */
    public static String download(String url, String path) {
        String respData = null;

        long sn = System.currentTimeMillis();
        try {
            log.info("jolley>> sn: {}, download url: {} to path: {}", sn, url, path);
            OkHttpClient client = new OkHttpClient();

            Request request = new Request.Builder()
                    .url(url)
                    .build();
            Response response = client.newCall(request).execute();

            if (!response.isSuccessful()) {
                throw new IOException("服务器端错误: " + response);
            }

            // 下载的文件名
            String filename = null;
            Headers responseHeaders = response.headers();
            for (int i = 0; i < responseHeaders.size(); i++) {
//				System.out.println("jolley>> " + responseHeaders.name(i) + ": " + responseHeaders.value(i));
                if ("Content-Type".equalsIgnoreCase(responseHeaders.name(i))) {
                    if (!"text/plain".equalsIgnoreCase(responseHeaders.value(i))) {
                        filename = UUID.randomUUID().toString();
                    }
                } else if ("Content-disposition".equalsIgnoreCase(responseHeaders.name(i))) {
                    String value = responseHeaders.value(i);
                    // 取文件名
//            		if(value.indexOf("filename=\"") > 0) {
//            			filename = value.substring(value.indexOf("filename=\"") + 10);
//            			if(filename.indexOf("\"") > 0) {
//            				filename.substring(0, filename.indexOf("\""));
//            			}
//            		}
                    // 取后缀名
                    if (value.lastIndexOf(".") > 0) {
                        String suffix = value.substring(value.lastIndexOf("."));
                        filename += suffix.replace("\"", "");
                    }
                    break;
                }
            }


            if (filename != null) {
                BufferedOutputStream bw = null;
                try {
                    String pathName = path;
                    if (pathName.endsWith("/")) {
                        pathName += filename;
                    }
                    // 创建文件对象
                    File f = new File(pathName);
                    // 创建文件路径
                    if (!f.getParentFile().exists()) {
                        f.getParentFile().mkdirs();
                    }
                    // 写入文件
                    bw = new BufferedOutputStream(new FileOutputStream(pathName));
                    bw.write(response.body().bytes());

                    respData = pathName;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (bw != null)
                            bw.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            } else {
                respData = response.body().string();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        log.info("jolley>> sn: {}, doPost response: {}", sn, respData);
        return respData;
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("startTime", "2020-01-01 01:01:01");
        map.put("endTime", "2028-01-01 01:01:01");
        map.put("deviceName", "MIMA-230414-01");
        String retString = NetworkUtils.doPost("https://farm.chnbreed.cn/mimaapi/record/getwdList", JSON.toJSONString(map), "application/json", 0, null);
        System.out.println("retString:" + retString);
    }

}
